//=============================================================================
//
//   Copyright (C) 2020 All rights reserved.
//
//   Filename:		mod.rs
//
//   Author: Wang Zhecheng - wangzhecheng@yeah.net
//
//   Date: 2020-10-19 00:51
//
//   Last Editors: Wang Zhecheng - wangzhecheng@yeah.net
//
//   Last modified:	2020-10-30 14:09
//
//   Description:
//
//=============================================================================
pub mod fem;
pub mod unknowns;
pub mod xfem;

use crate::component::model::Model;
use crate::dimension::DimType;
use crate::geometry::mesh::Mesh;
use crate::util::HasName;

pub trait NumericalMethodLike<DT: DimType> {
    fn build_mesh(&self, data: serde_json::Value, model: &mut Model<DT>);
}

#[derive(Debug)]
pub enum NumericalMethod<DT: DimType> {
    Fem(fem::Fem<DT>),
    Xfem(xfem::Xfem<DT>),
    None,
}
impl<DT: DimType> NumericalMethodLike<DT> for NumericalMethod<DT> {
    fn build_mesh(&self, data: serde_json::Value, model: &mut Model<DT>) {
        match self {
            NumericalMethod::Fem(v) => v.build_mesh(data, model),
            // NumericalMethod::Xfem(v) => v.build_mesh(data, model),
            _ => unimplemented!(),
        }
    }
}
impl<DT: DimType> HasName for NumericalMethod<DT> {
    fn type_name(&self) -> String {
        match self {
            NumericalMethod::Fem(_) => "Finite Element Method".to_string(),
            NumericalMethod::Xfem(_) => "Extended Finite Element Method".to_string(),
            _ => unimplemented!(),
        }
    }
    fn name() -> String
    where
        Self: Sized,
    {
        "".to_string()
    }
}

pub fn build_method<DT: DimType>(name: &str) -> NumericalMethod<DT> {
    match name.to_lowercase().as_str() {
        "fem" => NumericalMethod::Fem(fem::Fem::default()),
        "xfem" => NumericalMethod::Xfem(xfem::Xfem::default()),
        _ => panic!("Invalid method type {}", name),
    }
}
